#!/usr/hex2bin/env python
# -*- coding: UTF-8 -*-
#import psyco

import binascii
import table
import psyco
import threading
def Xor(s1, s2):
    """
    字符串xor
    
    s1 -- 第一个字符串
    s2 -- 第二个字符串
    """
    data={}
    data['0','1']=data['1','0']='1'
    data['0','0']=data['1','1']='0'
    s=[data[s1[x],s2[x]] for x in range(0,s1.__len__())]
    return ''.join(s)
    
def hex2bin(s):
    """
    返回一个16进制字符串的2进制形式。。把16进制变成2进制。
    
    s -- 字符串
    """

    data={'0':'0000','1':'0001','2':'0010','3':'0011','4':'0100',
		      '5':'0101','6':'0110','7':'0111','8':'1000','9':'1001',
		      'a':'1010','b':'1011','c':'1100','d':'1101','e':'1110',
		      'f':'1111'}
    b= ''.join([data[x] for x in s])
    return b

dec2bin = lambda n:''.join([hex2bin(x) for x in hex(n)[2:].rstrip('L')])

def bin2hex(x):
    data={'0000':'0','0001':'1','0010':'2','0011':'3','0100':'4',
            '0101':'5','0110':'6','0111':'7','1000':'8','1001':'9',
            '1010':'a','1011':'b','1100':'c','1101':'d','1110':'e',
	    '1111':'f'}
    s=makeList(x,4)
    l=[data[d] for d in s]
    return ''.join(l)

def easyDec2Bin(s):
    """
    简单的10进制转2进制,用于简化s_box操作
    
    s -- 10进制数
    """
    data={0:'0000',1:'0001',2:'0010',3:'0011',4:'0100',
		      5:'0101',6:'0110',7:'0111',8:'1000',9:'1001',
		      10:'1010',11:'1011',12:'1100',13:'1101',14:'1110',
		      15:'1111'}
    return data[s]

def fill64(s):
    """
    填充64bit。填充原则：最后一位是1,填0。0则填1。
    方法，如果刚刚好是64的整数倍，就填64bit,反之填余数个。

    s是16进制，返回2进制。
    """
    s=hex2bin(s)
    length = s.__len__()
    remainder = length%64
    if remainder == 0:
        remainder=64
    else:
        remainder=64-remainder
    last=s[-1]
    if last is '1':
        s=s+'0'*remainder
    else:
        s=s+'1'*remainder
    return s

def defill64(s):
    """
    反填充64bit

    s是2进制的形式。返回16进制
    """
    c=s[-1]
    if c is '0':
        pos=s.rindex('1')
        s=s[:pos+1]
    else:
        pos=s.rindex('0')
        s=s[:pos+1]
    return hex(int(s,2))[2:].rstrip('L')
def makeList(l, n):
    """
    根据n个步长生成list
    
    l -- 原列表
    n -- 步长
    """
    return [l[x:x+n] for x in xrange(0,l.__len__(),n)]
    
def makeKey(key):
        """
        生成16轮密钥
        """
        k=key
        c=[]
        d=[]
        k=''.join([k[x-1] for x in table.permuted_choice_1])
        c.append(k[:28])
        d.append(k[28:])
        def l_shift(l,n):
            """
            循环左移
            
            l -- 列表
            n -- 轮数
            """
            num = table.shift_table[n]
            return ''.join(l[num:]+l[:num])
        def permuted_2(l):
            """
            置换选择2
            
            l -- 列表
            """
            return ''.join([l[x-1] for x in table.permuted_choice_2])
        def makeNextKey(x):
            """
            生成下一个key
            
            x -- key
            """
            c.append(l_shift(c[x],x))
            d.append(l_shift(d[x],x))
            return permuted_2(c[x]+d[x])
            
        k=[makeNextKey(x) for x in range(0,16)]
        return k

class MyDes(object):

    def __init__(self,key):
        self.m=None
        self.k_list=makeKey(hex2bin(key))
        self.c=None

    def encrypt(self, s):
        """
        加密算法
        
        s -- 明文M
        k -- 密钥K
        """
        self.m=makeList(fill64(binascii.b2a_hex(s)),64)
        tl=[]
        for x in self.m:
            n=Encrypter64bit(x,self.k_list)
            tl.append(n)
            n.start()
        #s=[self.encrypt64bit(x) for x in self.m]
        s=[x.c for x in tl]
        s=''.join([bin2hex(x) for x in s])
        return binascii.a2b_hex(s)


    def decrypt(self, s):
        """
        解密算法

        s -- 密文C
        k -- 密钥K
        """
        self.c=binascii.b2a_hex(s)
        s=hex2bin(self.c)
        s=makeList(s,64)
        tl=[]
        for x in s:
            n=Decrypter64bit(x,self.k_list)
            tl.append(n)
            n.start()
        #s=[self.decrypt64bit(x) for x in s]
        s=''.join([x.m for x in tl])
        t=defill64(s)
        return binascii.a2b_hex(t)

   
class Encrypter64bit(threading.Thread):
    def __init__(self,m,keylist):
        threading.Thread.__init__(self)
        self.m=m
        self.k_list=keylist
        self.k_r=[self.k_list[0]]+self.k_list[1:][::-1]
        self.c=None
    def F(self, m, k):
        """
        Feistel。输入一个64bit的字符串.
        
        m -- mi-1
        k -- Ki
        """
        def s(s):
            """
            s_box
            
            in -- s
            """
            temp=[]
            for i in range(0,8):
                box=table.s_box[i]
                x=i*6
                p=int(s[x]+s[x+5],2)*16+int(s[x:x+4],2)
                temp.append(easyDec2Bin(box[p]))
            return ''.join(temp)
        l_p=m[:32]
        r_p=m[32:]
        e=''.join([r_p[x-1] for x in table.expansion])
        s_in= Xor(e,k)
        p_in=s(s_in)
        p_out=''.join([p_in[x-1] for x in table.permutation_p])
        r_now=Xor(l_p,p_out)
        return ''.join([r_p,r_now])

    def encrypt64bit(self, m):
        """
        对64bit进行加密,输入为64bit2进制的字符串
        
        m -- 明文，未经过初始置换
        k -- 密码，
        """
        m=''.join([m[x-1] for x in table.initial_permutation])
        for i in range(1,16):
            m=self.F(m,self.k_list[i])
        m=m[32:]+m[:32]
        c=''.join([m[x-1] for x in table.inverse_initial_permutation])
        return c
    def run(self):
        self.c=self.encrypt64bit(self.m)

class Decrypter64bit(threading.Thread):
    def __init__(self,c,keylist):
        threading .Thread.__init__(self)
        self.m=None
        self.k_list=keylist
        self.k_r=[self.k_list[0]]+self.k_list[1:][::-1]
        self.c=c

    def F(self, m, k):
        """
        Feistel。输入一个64bit的字符串.
        
        m -- mi-1
        k -- Ki
        """
        def s(s):
            """
            s_box
            
            in -- s
            """
            temp=[]
            for i in range(0,8):
                box=table.s_box[i]
                x=i*6
                p=int(s[x]+s[x+5],2)*16+int(s[x:x+4],2)
                temp.append(easyDec2Bin(box[p]))
            return ''.join(temp)
        l_p=m[:32]
        r_p=m[32:]
        e=''.join([r_p[x-1] for x in table.expansion])
        s_in= Xor(e,k)
        p_in=s(s_in)
        p_out=''.join([p_in[x-1] for x in table.permutation_p])
        r_now=Xor(l_p,p_out)
        return ''.join([r_p,r_now])
    def decrypt64bit(self, c):
        """
        对64bit进行解密，输入为64bit2进制的字符串。
        
        c -- 密文，未经过初始置换
        k -- 密码，
        """
        c=''.join([c[x-1] for x in table.initial_permutation])
        for i in range(1,16):
            c=self.F(c,self.k_r[i])
        c=c[32:]+c[:32]
        c=''.join([c[x-1] for x in table.inverse_initial_permutation])
        return c
    def run(self):
        self.m=self.decrypt64bit(self.c)
        
def main():
    k='1111111111111111'
    f=open('/home/linluxiang/banner.gif','rb')
    f2=open('/home/linluxiang/b.gif','wb')
    s=f.read()
    #s='1'*10000
    des=MyDes(k)
    a=des.encrypt(s)
    #print a.__len__()
    b=des.decrypt(a)
    print b.__len__()
    f2.write(b)
    f.close()
    f2.close()
        
        
if __name__ == '__main__':

    psyco.full()
    #import profile
    #profile.run('main()')
    main()
